/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mabi.modular.runtime.application;

import com.vaadin.Application;
import com.vaadin.Application.UserChangeListener;
import com.vaadin.Application.WindowAttachListener;
import com.vaadin.Application.WindowDetachListener;
import com.vaadin.service.ApplicationContext;
import com.vaadin.terminal.ApplicationResource;
import com.vaadin.terminal.DownloadStream;
import com.vaadin.terminal.Terminal;
import com.vaadin.terminal.URIHandler;
import com.vaadin.terminal.gwt.server.PortletApplicationContext;
import com.vaadin.terminal.gwt.server.WebApplicationContext;
import com.vaadin.ui.Window;
import java.net.URL;
import java.util.Collection;
import java.util.Locale;
import java.util.Properties;

/**
 *
 * @author Justo Disla
 */
public interface IApplication {

    /**
     * Adds the user change listener.
     *
     * This allows one to get notification each time {@link #setUser(Object)} is
     * called.
     *
     * @param listener
     * the user change listener to add.
     */
    void addListener(UserChangeListener listener);

    /**
     * Adds the window attach listener.
     *
     * Use this to get notifications each time a window is attached to the
     * application with {@link #addWindow(Window)}.
     *
     * @param listener
     * the window attach listener to add.
     */
    void addListener(WindowAttachListener listener);

    /**
     * Adds the window detach listener.
     *
     * Use this to get notifications each time a window is remove from the
     * application with {@link #removeWindow(Window)}.
     *
     * @param listener
     * the window detach listener to add.
     */
    void addListener(WindowDetachListener listener);

    /**
     * Adds new resource to the application. The resource can be accessed by the
     * user of the application.
     *
     * @param resource
     * the resource to add.
     */
    void addResource(ApplicationResource resource);

    /**
     * Adds a new window to the application.
     *
     * <p>
     * This implicitly invokes the
     * {@link com.vaadin.ui.Window#setApplication(Application)} method.
     * </p>
     *
     * <p>
     * Note that all application-level windows can be accessed by their names in
     * url <code>http://host:port/foo/bar/</code> where
     * <code>http://host:port/foo/</code> is the application url as returned by
     * getURL() and <code>bar</code> is the name of the window. Also note that
     * not all windows should be added to application - one can also add windows
     * inside other windows - these windows show as smaller windows inside those
     * windows.
     * </p>
     *
     * @param window
     * the new <code>Window</code> to add. If the name of the window
     * is <code>null</code>, an unique name is automatically given
     * for the window.
     * @throws IllegalArgumentException
     * if a window with the same name as the new window already
     * exists in the application.
     * @throws NullPointerException
     * if the given <code>Window</code> is <code>null</code>.
     */
    void addWindow(Window window) throws IllegalArgumentException, NullPointerException;

    /**
     * Ends the Application.
     *
     * <p>
     * In effect this will cause the application stop returning any windows when
     * asked. When the application is closed, its state is removed from the
     * session and the browser window is redirected to the application logout
     * url set with {@link #setLogoutURL(String)}. If the logout url has not
     * been set, the browser window is reloaded and the application is
     * restarted.
     * </p>
     * .
     */
    void close();

    /**
     * Gets the application context.
     * <p>
     * The application context is the environment where the application is
     * running in. The actual implementation class of may contains quite a lot
     * more functionality than defined in the {@link ApplicationContext}
     * interface.
     * </p>
     * <p>
     * By default, when you are deploying your application to a servlet
     * container, the implementation class is {@link WebApplicationContext} -
     * you can safely cast to this class and use the methods from there. When
     * you are deploying your application as a portlet, context implementation
     * is {@link PortletApplicationContext}.
     * </p>
     *
     * @return the application context.
     */
    ApplicationContext getContext();

    /**
     * Gets the application error handler.
     *
     * The default error handler is the application itself.
     *
     * @return Application error handler
     */
    Terminal.ErrorListener getErrorHandler();

    /**
     * Gets the default locale for this application.
     *
     * By default this is the preferred locale of the user using the
     * application. In most cases it is read from the browser defaults.
     *
     * @return the locale of this application.
     */
    Locale getLocale();

    /**
     * Returns the URL user is redirected to on application close. If the URL is
     * <code>null</code>, the application is closed normally as defined by the
     * application running environment.
     * <p>
     * Desktop application just closes the application window and
     * web-application redirects the browser to application main URL.
     * </p>
     *
     * @return the URL.
     */
    String getLogoutURL();

    /**
     * Gets the mainWindow of the application.
     *
     * <p>
     * The main window is the window attached to the application URL (
     * {@link #getURL()}) and thus which is show by default to the user.
     * </p>
     * <p>
     * Note that each application must have at least one main window.
     * </p>
     *
     * @return the main window.
     */
    Window getMainWindow();

    /**
     * Gets the relative uri of the resource. This method is intended to be
     * called only be the terminal implementation.
     *
     * This method can only be called from within the processing of a UIDL
     * request, not from a background thread.
     *
     * @param resource
     * the resource to get relative location.
     * @return the relative uri of the resource or null if called in a
     * background thread
     *
     * @deprecated this method is intended to be used by the terminal only. It
     * may be removed or moved in the future.
     */
    @Deprecated
    String getRelativeLocation(ApplicationResource resource);

    /**
     * Gets the application's theme. The application's theme is the default
     * theme used by all the windows in it that do not explicitly specify a
     * theme. If the application theme is not explicitly set, the
     * <code>null</code> is returned.
     *
     * @return the name of the application's theme.
     */
    String getTheme();

    /**
     * Gets the URL of the application.
     *
     * <p>
     * This is the URL what can be entered to a browser window to start the
     * application. Navigating to the application URL shows the main window (
     * {@link #getMainWindow()}) of the application. Note that the main window
     * can also be shown by navigating to the window url (
     * {@link com.vaadin.ui.Window#getURL()}).
     * </p>
     *
     * @return the application's URL.
     */
    URL getURL();

    /**
     * Gets the user of the application.
     *
     * <p>
     * Vaadin doesn't define of use user object in any way - it only provides
     * this getter and setter methods for convenience. The user is any object
     * that has been stored to the application with {@link #setUser(Object)}.
     * </p>
     *
     * @return the User of the application.
     */
    Object getUser();

    /**
     * Override this method to return correct version number of your
     * Application. Version information is delivered for example to Testing
     * Tools test results. By default this returns a string "NONVERSIONED".
     *
     * @return version string
     */
    String getVersion();

    /**
     * <p>
     * Gets a window by name. Returns <code>null</code> if the application is
     * not running or it does not contain a window corresponding to the name.
     * </p>
     *
     * <p>
     * All windows can be referenced by their names in url
     * <code>http://host:port/foo/bar/</code> where
     * <code>http://host:port/foo/</code> is the application url as returned by
     * getURL() and <code>bar</code> is the name of the window.
     * </p>
     *
     * <p>
     * One should note that this method can, as a side effect create new windows
     * if needed by the application. This can be achieved by overriding the
     * default implementation.
     * </p>
     *
     * <p>
     * If for some reason user opens another window with same url that is
     * already open, name is modified by adding "_12345678" postfix to the name,
     * where 12345678 is a random number. One can decide to create another
     * window-object for those windows (recommended) or to discard the postfix.
     * If the user has two browser windows pointing to the same window-object on
     * server, synchronization errors are likely to occur.
     * </p>
     *
     * <p>
     * If no browser-level windowing is used, all defaults are fine and this
     * method can be left as is. In case browser-level windows are needed, it is
     * recommended to create new window-objects on this method from their names
     * if the super.getWindow() does not find existing windows. See below for
     * implementation example: <code><pre>
     * // If we already have the requested window, use it
     * Window w = super.getWindow(name);
     * if (w == null) {
     * // If no window found, create it
     * w = new Window(name);
     * // set windows name to the one requested
     * w.setName(name);
     * // add it to this application
     * addWindow(w);
     * // ensure use of window specific url
     * w.open(new ExternalResource(w.getURL().toString()));
     * // add some content
     * w.addComponent(new Label("Test window"));
     * }
     * return w;</pre></code>
     * </p>
     *
     * <p>
     * <strong>Note</strong> that all returned Window objects must be added to
     * this application instance.
     *
     * <p>
     * The method should return null if the window does not exists (and is not
     * created as a side-effect) or if the application is not running anymore.
     * </p>
     *
     * @param name
     * the name of the window.
     * @return the window associated with the given URI or <code>null</code>
     */
    Window getWindow(String name);

    /**
     * Gets the set of windows contained by the application.
     *
     * <p>
     * Note that the returned set of windows can not be modified.
     * </p>
     *
     * @return the Unmodifiable collection of windows.
     */
    Collection<Window> getWindows();

    /**
     * Application URI handling hub.
     *
     * <p>
     * This method gets called by terminal. It has lots of duties like to pass
     * uri handler to proper uri handlers registered to windows etc.
     * </p>
     *
     * <p>
     * In most situations developers should NOT OVERRIDE this method. Instead
     * developers should implement and register uri handlers to windows.
     * </p>
     *
     * @deprecated this method is called be the terminal implementation only and
     * might be removed or moved in the future. Instead of
     * overriding this method, add your {@link URIHandler} to a top
     * level {@link Window} (eg.
     * getMainWindow().addUriHanler(handler) instead.
     */
    @Deprecated
    DownloadStream handleURI(URL context, String relativeUri);

    /**
     * <p>
     * Main initializer of the application. The <code>init</code> method is
     * called by the framework when the application is started, and it should
     * perform whatever initialization operations the application needs, such as
     * creating windows and adding components to them.
     * </p>
     */
    void init();

    /**
     * Tests if the application is running or if it has been finished.
     *
     * <p>
     * Application starts running when its
     * {@link #start(URL, Properties, ApplicationContext)} method has been
     * called and stops when the {@link #close()} is called.
     * </p>
     *
     * @return <code>true</code> if the application is running,
     * <code>false</code> if not.
     */
    boolean isRunning();

    /**
     * Removes the user change listener.
     *
     * @param listener
     * the user change listener to remove.
     */
    void removeListener(UserChangeListener listener);

    /**
     * Removes the window attach listener.
     *
     * @param listener
     * the window attach listener to remove.
     */
    void removeListener(WindowAttachListener listener);

    /**
     * Removes the window detach listener.
     *
     * @param listener
     * the window detach listener to remove.
     */
    void removeListener(WindowDetachListener listener);

    /**
     * Removes the resource from the application.
     *
     * @param resource
     * the resource to remove.
     */
    void removeResource(ApplicationResource resource);

    /**
     * Removes the specified window from the application.
     *
     * <p>
     * Removing the main window of the Application also sets the main window to
     * null. One must another window to be the main window after this with
     * {@link #setMainWindow(Window)}.
     * </p>
     *
     * <p>
     * Note that removing window from the application does not close the browser
     * window - the window is only removed from the server-side.
     * </p>
     *
     * @param window
     * the window to be removed.
     */
    void removeWindow(Window window);

    /**
     * Sets the application error handler.
     *
     * The default error handler is the application itself. By overriding this,
     * you can redirect the error messages to your selected target (log for
     * example).
     *
     * @param errorHandler
     */
    void setErrorHandler(Terminal.ErrorListener errorHandler);

    /**
     * Sets the default locale for this application.
     *
     * By default this is the preferred locale of the user using the
     * application. In most cases it is read from the browser defaults.
     *
     * @param locale
     * the Locale object.
     *
     */
    void setLocale(Locale locale);

    /**
     * Sets the URL user is redirected to on application close. If the URL is
     * <code>null</code>, the application is closed normally as defined by the
     * application running environment: Desktop application just closes the
     * application window and web-application redirects the browser to
     * application main URL.
     *
     * @param logoutURL
     * the logoutURL to set.
     */
    void setLogoutURL(String logoutURL);

    /**
     * <p>
     * Sets the mainWindow. If the main window is not explicitly set, the main
     * window defaults to first created window. Setting window as a main window
     * of this application also adds the window to this application.
     * </p>
     *
     * @param mainWindow
     * the mainWindow to set.
     */
    void setMainWindow(Window mainWindow);

    /**
     * Sets the application's theme.
     * <p>
     * Note that this theme can be overridden in the the application level
     * windows with {@link com.vaadin.ui.Window#setTheme(String)}. Setting theme
     * to be <code>null</code> selects the default theme. For the available
     * theme names, see the contents of the VAADIN/themes directory.
     * </p>
     *
     * @param theme
     * the new theme for this application.
     */
    void setTheme(String theme);

    /**
     * <p>
     * Sets the user of the application instance. An application instance may
     * have a user associated to it. This can be set in login procedure or
     * application initialization.
     * </p>
     * <p>
     * A component performing the user login procedure can assign the user
     * property of the application and make the user object available to other
     * components of the application.
     * </p>
     * <p>
     * Vaadin doesn't define of use user object in any way - it only provides
     * getter and setter methods for convenience. The user reference stored to
     * the application can be read with {@link #getUser()}.
     * </p>
     *
     * @param user
     * the new user.
     */
    void setUser(Object user);

    /**
     * Starts the application on the given URL.
     *
     * <p>
     * This method is called by Vaadin framework when a user navigates to the
     * application. After this call the application corresponds to the given URL
     * and it will return windows when asked for them. There is no need to call
     * this method directly.
     * </p>
     *
     * <p>
     * Application properties are defined by servlet configuration object
     * {@link javax.servlet.ServletConfig} and they are overridden by
     * context-wide initialization parameters
     * {@link javax.servlet.ServletContext}.
     * </p>
     *
     * @param applicationUrl
     * the URL the application should respond to.
     * @param applicationProperties
     * the Application properties as specified by the servlet
     * configuration.
     * @param context
     * the context application will be running in.
     *
     */
    void start(URL applicationUrl, Properties applicationProperties, ApplicationContext context);

    /**
     * <p>
     * Invoked by the terminal on any exception that occurs in application and
     * is thrown by the <code>setVariable</code> to the terminal. The default
     * implementation sets the exceptions as <code>ComponentErrors</code> to the
     * component that initiated the exception and prints stack trace to standard
     * error stream.
     * </p>
     * <p>
     * You can safely override this method in your application in order to
     * direct the errors to some other destination (for example log).
     * </p>
     *
     * @param event
     * the change event.
     * @see com.vaadin.terminal.Terminal.ErrorListener#terminalError(com.vaadin.terminal.Terminal.ErrorEvent)
     */
    void terminalError(Terminal.ErrorEvent event);
    
}
